"""
增强版网格交易策略

支持现货和合约网格，完全基于配置文件驱动
"""

import time
import math
from typing import Dict, List, Any, Optional, Tuple
from datetime import datetime
from .base_strategy import BaseStrategy
from ..core.exceptions import StrategyError, ValidationError
from ..core import unified_logger


class EnhancedGridStrategy(BaseStrategy):
    """增强版网格交易策略 - 支持现货和合约，配置驱动"""
    
    def __init__(self, config: Dict[str, Any], exchange_adapter, 
                 order_manager, account_manager, data_manager):
        """
        初始化增强版网格策略
        
        Args:
            config: 策略配置
            exchange_adapter: 交易所适配器
            order_manager: 订单管理器
            account_manager: 账户管理器
            data_manager: 数据管理器
        """
        super().__init__(config, exchange_adapter, order_manager, account_manager, data_manager)
        
        self.logger = unified_logger.get_logger(f"strategy_{self.name}")
        
        # 基础配置
        self.symbol = config.get('symbol', 'BTC-USDT')
        self.exchange = config.get('exchange', 'okx')
        self.trade_type = config.get('type', 'spot')  # spot/futures
        self.enabled = config.get('enabled', True)
        
        # 网格参数
        self.grid_count = config.get('grid_count', 10)
        self.price_range_percent = config.get('price_range_percent', 0.08)
        self.base_order_size = config.get('base_order_size', 50.0)
        self.profit_ratio = config.get('profit_ratio', 0.005)
        
        # 风险控制
        self.stop_loss_ratio = config.get('stop_loss_ratio', 0.05)
        self.max_position_ratio = config.get('max_position_ratio', 0.3)
        
        # 合约特有参数
        self.leverage = config.get('leverage', 1) if self.trade_type == 'futures' else 1
        self.position_side = config.get('position_side', 'both')  # long/short/both
        
        # 其他参数
        self.interval = config.get('interval', '1m')
        
        # 运行时状态
        self.grid_levels = []
        self.active_orders = {}
        self.filled_orders = []
        self.current_price = 0.0
        self.base_price = 0.0
        self.price_min = 0.0
        self.price_max = 0.0
        self.total_profit = 0.0
        self.total_trades = 0
        self.last_check_time = 0
        
        # 初始化验证
        self._validate_config()
        
    def _validate_config(self) -> None:
        """验证策略配置"""
        if not self.symbol:
            raise ValidationError("交易对不能为空")
            
        if not self.exchange:
            raise ValidationError("交易所不能为空")
            
        if self.trade_type not in ['spot', 'futures']:
            raise ValidationError("交易类型必须是 spot 或 futures")
            
        if self.grid_count < 3:
            raise ValidationError("网格数量不能少于3个")
            
        if self.price_range_percent <= 0 or self.price_range_percent > 1:
            raise ValidationError("价格范围百分比必须在0-1之间")
            
        if self.base_order_size <= 0:
            raise ValidationError("基础订单金额必须大于0")
            
        if self.profit_ratio <= 0:
            raise ValidationError("利润比例必须大于0")
            
        if self.trade_type == 'futures' and (self.leverage < 1 or self.leverage > 100):
            raise ValidationError("合约杠杆倍数必须在1-100之间")
            
        self.logger.info(f"策略配置验证通过: {self.symbol} {self.trade_type}")
    
    def initialize(self) -> bool:
        """初始化策略"""
        try:
            self.logger.info(f"初始化 {self.symbol} {self.trade_type} 网格策略...")
            
            # 获取当前价格
            ticker = self.exchange_adapter.get_ticker(self.symbol)
            if not ticker:
                raise StrategyError(f"无法获取 {self.symbol} 价格信息")
                
            self.current_price = float(ticker.get('last', 0))
            if self.current_price <= 0:
                raise StrategyError(f"无效的价格: {self.current_price}")
            
            # 设置基准价格
            self.base_price = self.current_price
            
            # 计算价格范围
            self._calculate_price_range()
            
            # 生成网格层级
            self._generate_grid_levels()
            
            # 检查资金充足性
            if not self._check_sufficient_funds():
                raise StrategyError("资金不足，无法启动网格策略")
            
            # 设置杠杆(仅合约)
            if self.trade_type == 'futures':
                self._set_leverage()
            
            # 放置初始网格订单
            self._place_initial_grid_orders()
            
            self.logger.info(f"网格策略初始化完成: {len(self.grid_levels)} 个网格层级")
            return True
            
        except Exception as e:
            self.logger.error(f"策略初始化失败: {e}")
            return False
    
    def _calculate_price_range(self) -> None:
        """计算价格范围"""
        range_amount = self.current_price * self.price_range_percent
        self.price_min = self.current_price - range_amount
        self.price_max = self.current_price + range_amount
        
        self.logger.info(f"价格范围: {self.price_min:.4f} - {self.price_max:.4f}")
    
    def _generate_grid_levels(self) -> None:
        """生成网格层级"""
        self.grid_levels = []
        
        # 计算网格间距
        grid_spacing = (self.price_max - self.price_min) / self.grid_count
        
        for i in range(self.grid_count + 1):
            price = self.price_min + i * grid_spacing
            
            grid_level = {
                'level': i,
                'price': price,
                'buy_price': price,
                'sell_price': price * (1 + self.profit_ratio),
                'amount': self.base_order_size / price,  # 计算数量
                'status': 'pending',  # pending/buy_filled/sell_filled
                'buy_order_id': None,
                'sell_order_id': None,
                'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S')  # 统一格式
            }
            
            self.grid_levels.append(grid_level)
        
        self.logger.info(f"生成 {len(self.grid_levels)} 个网格层级")
    
    def _check_sufficient_funds(self) -> bool:
        """检查资金充足性"""
        try:
            balance = self.account_manager.get_balance()
            
            if self.trade_type == 'spot':
                # 现货需要检查USDT余额
                usdt_balance = balance.get('USDT', {}).get('available', 0)
                required_usdt = self.base_order_size * len(self.grid_levels) / 2
                
                if usdt_balance < required_usdt:
                    self.logger.error(f"USDT余额不足: {usdt_balance} < {required_usdt}")
                    return False
                    
            else:
                # 合约需要检查保证金
                margin_balance = balance.get('margin', {}).get('available', 0)
                required_margin = (self.base_order_size * len(self.grid_levels)) / self.leverage
                
                if margin_balance < required_margin:
                    self.logger.error(f"保证金不足: {margin_balance} < {required_margin}")
                    return False
            
            return True
            
        except Exception as e:
            self.logger.error(f"检查资金失败: {e}")
            return False
    
    def _set_leverage(self) -> None:
        """设置杠杆(仅合约)"""
        if self.trade_type == 'futures':
            try:
                self.exchange_adapter.set_leverage(self.symbol, self.leverage)
                self.logger.info(f"设置杠杆: {self.leverage}x")
            except Exception as e:
                self.logger.error(f"设置杠杆失败: {e}")
    
    def _place_initial_grid_orders(self) -> None:
        """放置初始网格订单"""
        for grid_level in self.grid_levels:
            # 只在当前价格下方放置买单
            if grid_level['price'] < self.current_price:
                self._place_buy_order(grid_level)
    
    def _place_buy_order(self, grid_level: Dict[str, Any]) -> None:
        """放置买单"""
        try:
            order_params = {
                'symbol': self.symbol,
                'side': 'buy',
                'type': 'limit',
                'amount': grid_level['amount'],
                'price': grid_level['buy_price']
            }
            
            if self.trade_type == 'futures':
                order_params['position_side'] = 'long'
            
            order = self.order_manager.place_order(**order_params)
            
            if order and order.get('id'):
                grid_level['buy_order_id'] = order['id']
                grid_level['status'] = 'buy_pending'
                self.active_orders[order['id']] = {
                    'grid_level': grid_level['level'],
                    'type': 'buy'
                }
                
                self.logger.info(f"放置买单: 价格={grid_level['buy_price']:.4f}, "
                               f"数量={grid_level['amount']:.6f}")
                
        except Exception as e:
            self.logger.error(f"放置买单失败: {e}")
    
    def _place_sell_order(self, grid_level: Dict[str, Any]) -> None:
        """放置卖单"""
        try:
            order_params = {
                'symbol': self.symbol,
                'side': 'sell',
                'type': 'limit',
                'amount': grid_level['amount'],
                'price': grid_level['sell_price']
            }
            
            if self.trade_type == 'futures':
                order_params['position_side'] = 'short'
            
            order = self.order_manager.place_order(**order_params)
            
            if order and order.get('id'):
                grid_level['sell_order_id'] = order['id']
                grid_level['status'] = 'sell_pending'
                self.active_orders[order['id']] = {
                    'grid_level': grid_level['level'],
                    'type': 'sell'
                }
                
                self.logger.info(f"放置卖单: 价格={grid_level['sell_price']:.4f}, "
                               f"数量={grid_level['amount']:.6f}")
                
        except Exception as e:
            self.logger.error(f"放置卖单失败: {e}")
    
    def on_tick(self, data: Dict[str, Any]) -> None:
        """处理价格更新"""
        if not self.enabled:
            return
            
        current_time = time.time()
        if current_time - self.last_check_time < 60:  # 1分钟检查一次
            return
            
        self.last_check_time = current_time
        
        # 更新当前价格
        if 'price' in data:
            self.current_price = float(data['price'])
        
        # 检查止损
        if self._check_stop_loss():
            return
        
        # 检查网格订单状态
        self._check_grid_orders()
        
        # 动态调整网格(如果需要)
        self._adjust_grid_if_needed()
    
    def on_order_update(self, order: Dict[str, Any]) -> None:
        """处理订单更新"""
        order_id = order.get('id')
        if order_id not in self.active_orders:
            return
        
        grid_info = self.active_orders[order_id]
        grid_level = self.grid_levels[grid_info['grid_level']]
        
        if order.get('status') == 'filled':
            self._handle_order_filled(order, grid_info, grid_level)
        elif order.get('status') in ['cancelled', 'rejected']:
            self._handle_order_cancelled(order, grid_info, grid_level)
    
    def _handle_order_filled(self, order: Dict[str, Any], 
                           grid_info: Dict[str, Any], 
                           grid_level: Dict[str, Any]) -> None:
        """处理订单成交"""
        order_type = grid_info['type']
        filled_price = float(order.get('price', 0))
        filled_amount = float(order.get('amount', 0))
        
        if order_type == 'buy':
            # 买单成交，放置对应的卖单
            grid_level['status'] = 'buy_filled'
            self._place_sell_order(grid_level)
            
            self.logger.info(f"买单成交: 价格={filled_price:.4f}, 数量={filled_amount:.6f}")
            
        elif order_type == 'sell':
            # 卖单成交，计算利润并放置新的买单
            grid_level['status'] = 'sell_filled'
            
            # 计算利润
            profit = (filled_price - grid_level['buy_price']) * filled_amount
            self.total_profit += profit
            self.total_trades += 1
            
            # 重新放置买单
            grid_level['status'] = 'pending'
            grid_level['buy_order_id'] = None
            grid_level['sell_order_id'] = None
            self._place_buy_order(grid_level)
            
            self.logger.info(f"卖单成交: 价格={filled_price:.4f}, 数量={filled_amount:.6f}, "
                           f"利润={profit:.4f}")
        
        # 从活跃订单中移除
        if order.get('id') in self.active_orders:
            del self.active_orders[order.get('id')]
        
        # 记录成交订单
        self.filled_orders.append({
            'order_id': order.get('id'),
            'type': order_type,
            'price': filled_price,
            'amount': filled_amount,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),  # 统一格式
            'grid_level': grid_info['grid_level']
        })
    
    def _handle_order_cancelled(self, order: Dict[str, Any], 
                              grid_info: Dict[str, Any], 
                              grid_level: Dict[str, Any]) -> None:
        """处理订单取消"""
        order_type = grid_info['type']
        
        # 重置网格状态
        if order_type == 'buy':
            grid_level['buy_order_id'] = None
            grid_level['status'] = 'pending'
        else:
            grid_level['sell_order_id'] = None
            grid_level['status'] = 'buy_filled'
        
        # 从活跃订单中移除
        if order.get('id') in self.active_orders:
            del self.active_orders[order.get('id')]
        
        self.logger.warning(f"{order_type}单被取消: 订单ID={order.get('id')}")
    
    def _check_grid_orders(self) -> None:
        """检查网格订单状态"""
        for order_id in list(self.active_orders.keys()):
            try:
                order = self.order_manager.get_order(order_id)
                if order:
                    self.on_order_update(order)
            except Exception as e:
                self.logger.error(f"检查订单状态失败: {e}")
    
    def _check_stop_loss(self) -> bool:
        """检查止损"""
        if self.stop_loss_ratio <= 0:
            return False
        
        # 计算止损价格
        stop_loss_price = self.base_price * (1 - self.stop_loss_ratio)
        
        if self.current_price <= stop_loss_price:
            self.logger.warning(f"触发止损: 当前价格={self.current_price:.4f}, "
                              f"止损价格={stop_loss_price:.4f}")
            self._execute_stop_loss()
            return True
        
        return False
    
    def _execute_stop_loss(self) -> None:
        """执行止损"""
        try:
            # 取消所有活跃订单
            for order_id in list(self.active_orders.keys()):
                self.order_manager.cancel_order(order_id)
            
            # 清空活跃订单
            self.active_orders.clear()
            
            # 禁用策略
            self.enabled = False
            
            self.logger.info("止损执行完成，策略已停止")
            
        except Exception as e:
            self.logger.error(f"执行止损失败: {e}")
    
    def _adjust_grid_if_needed(self) -> None:
        """动态调整网格(如果需要)"""
        # 检查价格是否超出网格范围
        if self.current_price < self.price_min * 0.95:
            self._extend_grid_down()
        elif self.current_price > self.price_max * 1.05:
            self._extend_grid_up()
    
    def _extend_grid_down(self) -> None:
        """向下扩展网格"""
        self.logger.info("价格下跌，向下扩展网格")
        # 重新计算价格范围和网格
        self._calculate_price_range()
        self._generate_grid_levels()
        self._place_initial_grid_orders()
    
    def _extend_grid_up(self) -> None:
        """向上扩展网格"""
        self.logger.info("价格上涨，向上扩展网格")
        # 重新计算价格范围和网格
        self._calculate_price_range()
        self._generate_grid_levels()
        self._place_initial_grid_orders()
    
    def get_status(self) -> Dict[str, Any]:
        """获取策略状态"""
        return {
            'name': self.name,
            'symbol': self.symbol,
            'exchange': self.exchange,
            'type': self.trade_type,
            'enabled': self.enabled,
            'current_price': self.current_price,
            'base_price': self.base_price,
            'price_range': [self.price_min, self.price_max],
            'grid_count': len(self.grid_levels),
            'active_orders': len(self.active_orders),
            'total_trades': self.total_trades,
            'total_profit': self.total_profit,
            'profit_ratio': (self.total_profit / (self.base_order_size * len(self.grid_levels))) * 100 if self.grid_levels else 0
        }
    
    def get_detailed_status(self) -> Dict[str, Any]:
        """获取详细状态"""
        status = self.get_status()
        
        # 添加网格详情
        grid_details = []
        for grid in self.grid_levels:
            grid_details.append({
                'level': grid['level'],
                'price': grid['price'],
                'status': grid['status'],
                'buy_order_id': grid['buy_order_id'],
                'sell_order_id': grid['sell_order_id']
            })
        
        status['grid_details'] = grid_details
        status['filled_orders'] = self.filled_orders[-10:]  # 最近10笔成交
        
        return status
    
    def stop(self) -> None:
        """停止策略"""
        self.logger.info("停止网格策略...")
        
        # 取消所有活跃订单
        for order_id in list(self.active_orders.keys()):
            try:
                self.order_manager.cancel_order(order_id)
            except Exception as e:
                self.logger.error(f"取消订单失败: {e}")
        
        # 清空状态
        self.active_orders.clear()
        self.enabled = False
        
        self.logger.info("网格策略已停止")